#include "audio_decoder.h"
#include <speex/speex.h>
#include "adpcm-pcm.h"
#include "mqtt.h"
#include "eth.h"
#include "CONFIG.h"
#include "wchble.h"
#if 1

uint8_t Audio_Decode_TaskID;


Audio_Decode_t audio_decode = {0};



void *decoder_state = NULL;
// Initialization of the structure that holds the bits
static SpeexBits bits;

//adpcm 解码状态
static ima_adpcm_state_t* state = NULL;



static uint8_t data[AUDIO_DECODE_FRAME_LEN*2] = {0};
static uint8_t decode_data[AUDIO_DECODE_FRAME_LEN*4] = {0};

#if 1
	
	//音频解码任务
 uint16_t AUDIO_DECODE_ProcessEvent(uint8_t task_id, uint16_t events)
{
	uint16_t wait_decode_size = 0,wait_act_len = 0,wait_send_network_size = 0;
	uint16_t buffer_size = 0,act_len = 0,encode_speex_len = 0;


	#if 1
	if(events & SYS_EVENT_MSG)
    {
        Send_Msg_t  *pMsg;

        if((pMsg = tmos_msg_receive(Audio_Decode_TaskID)) != NULL)
        {
               //printf("msg receive\r\n");

             if(mqtt_config.is_connect == true)
             {
//                 for(int i =0 ;i<pMsg->len;i++)
//                 {
//                     printf("%02x",pMsg->data[i]);
//                 }
                if(pMsg->type == MQTT_DATA_VOICE_TYPE)
                {
                        if(pMsg->code == MQTT_VOICE_TYPE_STATUS_FIRST_FRAME)
                        {
                            printf("ble FIRST_FRAME\r\n");
                        }
                           if(pMsg->code == MQTT_VOICE_TYPE_STATUS_CONTINUE_FRAME)
                        {
                            //printf("ble CONTINUE_FRAME\r\n");
                        }
                           if(pMsg->code == MQTT_VOICE_TYPE_STATUS_LAST_FRAME)
                        {
                            printf("ble LAST_FRAME\r\n");
                        }
                        //MQTT_Publish((char *)&mqtt_config.Subscribed_topic[0][0],0,(char *)pMsg->data,pMsg->len);
                        //MQTT_Send_Publish(pMsg->type  ,pMsg->code,(char *)pMsg->data,pMsg->len);


							audio_decode.status = DECODER_STATE_BUSY;

							//wait_decode_size = get_audio_decoder_valid_size();

							act_len = y_ringbuf_read_clear(audio_decode.adpcm_in_ringbuffer,data,AUDIO_DECODE_FRAME_LEN);

							int len = ima_adpcm_decode(state,decode_data,data,act_len);
							
							audio_decode.status = DECODER_STATE_IDLE;
							//printf("decode len %d\r\n",len);
							// tmos_start_task(Audio_Decode_TaskID, ETH_SENG_DATA_EVENT, 1600);

							wait_send_network_size = get_audio_decoder_output_valid_size();

							//audio_speex_encode(decode_data,data,encode_speex_len);
							//audio_decoder_dst_output(data,encode_speex_len);
							audio_decoder_dst_output(decode_data,len<<1);
					
							if(wait_send_network_size>=(320/*AUDIO_DECODE_FRAME_LEN*/))
							{


								

								Send_Msg_t * msg = tmos_msg_allocate(sizeof(Send_Msg_t));

								if(msg)
								{
										msg->type = MQTT_DATA_VOICE_TYPE;

										if(audio_decode.code == 0xff)
										{
											audio_decode.code = MQTT_VOICE_TYPE_STATUS_FIRST_FRAME;
											msg->code = audio_decode.code;
										}
										else if(audio_decode.code== MQTT_VOICE_TYPE_STATUS_FIRST_FRAME)
										{
											audio_decode.code = MQTT_VOICE_TYPE_STATUS_CONTINUE_FRAME;
											msg->code = audio_decode.code;
										}else if((audio_decode.code== MQTT_VOICE_TYPE_STATUS_CONTINUE_FRAME))
										{
											
											if(pMsg->code == MQTT_VOICE_TYPE_STATUS_LAST_FRAME)
											{
												
												audio_decode.code = MQTT_VOICE_TYPE_STATUS_LAST_FRAME;
												msg->code = audio_decode.code;
												audio_decode.code = 0xff;

											}else if(pMsg->code == MQTT_VOICE_TYPE_STATUS_CONTINUE_FRAME)
											{
												audio_decode.code = MQTT_VOICE_TYPE_STATUS_CONTINUE_FRAME;
												msg->code = audio_decode.code;
												
											}

										}
										
										#if 1
										msg->data = (uint8_t *)malloc(320);
										if(msg->data == NULL)
										{
											printf("malloc fail\r\n");
										}
										memset(msg->data,0x00,320);

										act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,320);
										audio_speex_encode((char *)msg->data,(char *)data,&encode_speex_len);
										memcpy(msg->data,data,encode_speex_len);
										msg->len = encode_speex_len; 
										#else
										act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,AUDIO_DECODE_FRAME_LEN);
										msg->len = act_len;
										#endif
										tmos_msg_send(eth_TaskID, (uint8_t *)msg);
								}
                		}else
						{
							//上传最后一帧送数据
							 if(((pMsg->code == MQTT_VOICE_TYPE_STATUS_LAST_FRAME))&&(audio_decode.code== MQTT_VOICE_TYPE_STATUS_CONTINUE_FRAME))
								{

								
								printf("final ble LAST_FRAME\r\n");

								audio_decode.code = MQTT_VOICE_TYPE_STATUS_LAST_FRAME;

								Send_Msg_t * msg = tmos_msg_allocate(sizeof(Send_Msg_t));

									if(msg)
									{
											msg->type = MQTT_DATA_VOICE_TYPE;
											msg->code = audio_decode.code;
											#if 1
											msg->data = (uint8_t *)malloc(20);
											memset(msg->data,0x00,20);

											//act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,320);
											//audio_speex_encode((char *)msg->data,(char *)data,&encode_speex_len);
											//memcpy(msg->data,data,encode_speex_len);
											msg->len = 20; 
											#else
											act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,AUDIO_DECODE_FRAME_LEN);
											msg->len = act_len;
											#endif
											tmos_msg_send(eth_TaskID, (uint8_t *)msg);
									}
									audio_decode.code = 0xff;
								}
							


						}
                 //MQTT_Publish((char *)&mqtt_config.Subscribed_topic[0][0],0,(char *)pMsg->data,pMsg->len);
             }


             free(pMsg->data);
            // Release the TMOS message
            tmos_msg_deallocate(pMsg);
        }
	}
        // return unprocessed events
        return (events ^ SYS_EVENT_MSG);
    }
	#endif
    if(events & AUDIO_START_DECODE_EVENT)	
    {
		#if 1
		audio_decode.status = DECODER_STATE_BUSY;

		//wait_decode_size = get_audio_decoder_valid_size();

		act_len = y_ringbuf_read_clear(audio_decode.adpcm_in_ringbuffer,data,AUDIO_DECODE_FRAME_LEN);

		int len = ima_adpcm_decode(state,decode_data,data,act_len);
		
		audio_decode.status = DECODER_STATE_IDLE;
		//printf("decode len %d\r\n",len);
        // tmos_start_task(Audio_Decode_TaskID, ETH_SENG_DATA_EVENT, 1600);

		wait_send_network_size = get_audio_decoder_output_valid_size();

		//wait_send_network_size = get_audio_decoder_output_valid_size();
		 //audio_speex_encode(decode_data,data,encode_speex_len);
		 //audio_decoder_dst_output(data,encode_speex_len);
 		audio_decoder_dst_output(decode_data,len<<1);

								if(wait_send_network_size>=(320/*AUDIO_DECODE_FRAME_LEN*/))
							{


								

								Send_Msg_t * msg = tmos_msg_allocate(sizeof(Send_Msg_t));

								if(msg)
								{
										msg->type = MQTT_DATA_VOICE_TYPE;
										//msg->code = pMsg->code;
										#if 1
										msg->data = (uint8_t *)malloc(320);
										memset(msg->data,0x00,320);

										act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,320);
										audio_speex_encode((char *)msg->data,(char *)data,&encode_speex_len);
										memcpy(msg->data,data,encode_speex_len);
									

									
										msg->len = encode_speex_len; 
										#else
										act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,AUDIO_DECODE_FRAME_LEN);
										msg->len = act_len;
										#endif

				

										tmos_msg_send(eth_TaskID, (uint8_t *)msg);
								}


                }
 
		// if(wait_send_network_size>=(AUDIO_DECODE_FRAME_LEN))
		// {

		// 	Send_Msg_t * msg = tmos_msg_allocate(sizeof(Send_Msg_t));

		// 	if(msg)
		// 	{
		// 			msg->type = MQTT_DATA_VOICE_TYPE;
		// 			msg->data = (uint8_t *)malloc(AUDIO_DECODE_FRAME_LEN);
		// 			memset(msg->data,0x00,AUDIO_DECODE_FRAME_LEN);

		// 			act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,AUDIO_DECODE_FRAME_LEN);

		// 			msg->len = act_len;

		// 			tmos_msg_send(eth_TaskID, (uint8_t *)msg);
		// 	}



		// 	//tmos_set_event(Audio_Decode_TaskID,AUDIO_START_DECODE_EVENT);
		// 	//tmos_start_task(Audio_Decode_TaskID, AUDIO_START_DECODE_EVENT, 1600);
		// }
		#else


		uint8_t cmd[5] = {0};
		audio_decode.status = DECODER_STATE_BUSY;

		wait_decode_size = get_audio_decoder_valid_size();
		act_len = y_ringbuf_read_only(audio_decode.adpcm_in_ringbuffer,data,wait_decode_size);

			if(1)//if((data[0]==0x55) && (data[1]==0xAA))
		  {
					act_len = y_ringbuf_read_clear(audio_decode.adpcm_in_ringbuffer,cmd,5);
					//if(act_len == 5)
					{
							act_len = y_ringbuf_read_clear(audio_decode.adpcm_in_ringbuffer,data,cmd[4]);

							int len = ima_adpcm_decode(state,decode_data,data,act_len);
							
							audio_decode.status = DECODER_STATE_IDLE;
							//printf("decode len %d\r\n",len);
							// tmos_start_task(Audio_Decode_TaskID, ETH_SENG_DATA_EVENT, 1600);

							wait_send_network_size = get_audio_decoder_output_valid_size();
							audio_decoder_dst_output(decode_data,len<<1);
					
							//if(wait_send_network_size>=(cmd[4]*4))
							{
								Send_Msg_t * msg = tmos_msg_allocate(sizeof(Send_Msg_t));

								if(msg)
								{
										msg->type = cmd[2];
										msg->code = cmd[3];
										msg->data = (uint8_t *)malloc(cmd[4]*4);
										memset(msg->data,0x00,cmd[4]*4);
										act_len = y_ringbuf_read_clear(audio_decode.decoder_out_ringbuffer,msg->data,cmd[4]*4);
										msg->len = cmd[4];
										//printf("msg->type %d,msg->code %d,msg->len %d\r\n",cmd[2],cmd[3],cmd[4]);
										tmos_msg_send(eth_TaskID, (uint8_t *)msg);
								}
							}

					}
			}else
			{
				printf("fail\r\n");
			}

					













		#endif














    return (events ^ AUDIO_START_DECODE_EVENT);

    }else if(events & AUDIO_STOP_DECODE_EVENT)
    {
		
        // uint32_t stata;
        // uint8_t data[2] = {0x77};
        // stata = eth_send(data, 2);
        // if( stata )
        // {
        //     printf("eth send fail %x \n",stata);
        // }
        // tmos_start_task(Audio_Decode_TaskID, ETH_SENG_DATA_EVENT, 1600);
        return (events ^ AUDIO_STOP_DECODE_EVENT);

    }
	else if(events & AUDIO_DECODE_EVENT)
    {
		//准备进行解码操作

		//wait_decode_size = get_audio_decoder_valid_size();

		//if(wait_decode_size>=AUDIO_DECODE_FRAME_LEN)
		{
			tmos_set_event(Audio_Decode_TaskID,AUDIO_START_DECODE_EVENT);
			//tmos_start_task(Audio_Decode_TaskID, AUDIO_START_DECODE_EVENT, 1600);
		}

        
        return (events ^ AUDIO_DECODE_EVENT);
    }

}

#endif

void audio_decoder_init(void)
{
	audio_decode.status = DECODER_STATE_IDLE;
	audio_decode.code = 0xff;
	audio_decode.adpcm_in_ringbuffer = y_ringbuf_create(RINGBUFFER_DECODE_LEN);
	audio_decode.decoder_out_ringbuffer = y_ringbuf_create(RINGBUFFER_DECODE_LEN);

	// // Set quality to 8 (15 kbps)
	// uint32_t frame_size= 0;
	// // 设置编码器和解码器参数
	// int sample_rate = 8000;
	// int quality = 4;

	// decoder_state = speex_decoder_init(&speex_nb_mode);
	// // Set the perceptual enhancement on
    // uint32_t tmp = 1;
    // speex_decoder_ctl(decoder_state, SPEEX_SET_ENH, &tmp);
	// //speex_decoder_ctl(decoder_state, SPEEX_SET_SAMPLING_RATE, &sample_rate);
	// //speex_decoder_ctl(decoder_state,SPEEX_GET_FRAME_SIZE,&frame_size);
	// //speex_decoder_ctl(decoder_state, SPEEX_SET_QUALITY, &quality);

	// speex_bits_init(&bits);
	// char in[20]={0};
	// for(int i = 0;i<20;i++)
	// {
	// 	in[i]= i; 
	// }
	// char out[320]={0};
	// audio_speex_decode(in,out,20);


		
		
	/*Init adpcm*/
	state = ima_adpcm_init(state, IMA_ADPCM_DVI4);
	if (state == NULL)
	{
		/* code */
		printf("adpcm init fail\r\n");
	}
	


	Audio_Decode_TaskID = TMOS_ProcessEventRegister(AUDIO_DECODE_ProcessEvent);
	
}


void audio_speex_decode(uint8_t *in,uint8_t *out,int len)
{
        //printf("%s\r\n",__FUNCTION__);
		//speex_bits_reset(&bits);
		 // Copy the data into the bit-stream struct
        speex_bits_read_from(&bits, in, len);
        speex_decode_int(decoder_state, &bits ,(short *)out);
		//speex_bits_nbytes(&bits);
        // Copy the bits to an array of char that can be written
        //size_t s = speex_bits_write(&bits, (char *)out, 320);

		//*len = s;
		//printf("encode size %d\r\n",s);
}









 __attribute__((section("ram_code"))) void audio_decoder_start(void)
{
	//printf("audio_encoder_start\r\n");
	uint16_t buffer_size = 0,act_len = 0;
	memset(data,0,sizeof(data));
	memset(data,0,sizeof(decode_data));
	//buffer_size = get_audio_encoder_valid_size();
	//if(buffer_size>=AUDIO_DECODE_FRAME_LEN)
	{
	    audio_decode.status = DECODER_STATE_BUSY;
		//printf("1 heap size %d\r\n",os_get_free_heap_size());
			//speex_bits_reset(&bits);
			act_len = y_ringbuf_read_clear(audio_decode.adpcm_in_ringbuffer,data,AUDIO_DECODE_FRAME_LEN);
		
			//Encode frame
		#if 0
        speex_encode_int(encoder_state, (short *)data, &bits);
				//speex_bits_nbytes(&bits);
        // Copy the bits to an array of char that can be written
        size_t s = speex_bits_write(&bits, (char *)encode_data, AUDIO_DECODE_FRAME_LEN);
				printf("2 heap size %d\r\n",os_get_free_heap_size());	
				printf("src size %d,encode size %d\r\n",act_len,s);
		#else
		
		int len = ima_adpcm_encode(state, decode_data,(uint16_t*)data, act_len);
		printf("Encode data length is:%d\r\n", len);
	
		
		#endif
		audio_decode.status = DECODER_STATE_IDLE;
	}
	
}

void audio_decoder_stop(void)
{
	
}

void audio_reset_decoder_ringbuffer()
{
	y_ringbuf_reset(audio_decode.adpcm_in_ringbuffer);
}

 __attribute__((section("ram_code"))) bool audio_decoder_src_input(uint8_t*data,uint16_t len)
{
		return y_ringbuf_write(audio_decode.adpcm_in_ringbuffer,data, len);
}

 __attribute__((section("ram_code"))) uint16_t get_audio_decoder_valid_size()
{
	return y_ringbuf_get_used_size(audio_decode.adpcm_in_ringbuffer);
}


 __attribute__((section("ram_code"))) bool audio_decoder_dst_output(uint8_t*data,uint16_t len)
{
		return y_ringbuf_write(audio_decode.decoder_out_ringbuffer,data, len);
}

 __attribute__((section("ram_code"))) uint16_t get_audio_decoder_output_valid_size()
{
	return y_ringbuf_get_used_size(audio_decode.decoder_out_ringbuffer);
}




 __attribute__((section("ram_code"))) bool get_audio_decoder_is_busy(void)
{
		if(audio_decode.status == DECODER_STATE_BUSY)
			return true;
		else
			return false;
}


void Audio_Decode_Send_Event()
{
	tmos_set_event(Audio_Decode_TaskID,AUDIO_DECODE_EVENT);
}


void Audio_Decode_Send_Msg(uint8_t type,uint8_t code,uint8_t len)
{
    Send_Msg_t * msg = tmos_msg_allocate(sizeof(Send_Msg_t));

        if(msg)
        {       msg->type = type;
                msg->code = code;
                msg->data = NULL;
                msg->len = len;
                //printf("msg->type %d,msg->code %d,msg->len %d\r\n",cmd[2],cmd[3],cmd[4]);
                tmos_msg_send(Audio_Decode_TaskID, (uint8_t *)msg);
        }
}

#if 0
 __attribute__((section("ram_code"))) void msg_post_decode_handler()
{
	//printf("%s\r\n",__FUNCTION__);
	os_event_t event={0};
	event.event_id = ENCODER_EVENT;
	event.src_task_id = TASK_ID_NONE;
	event.param = NULL;
	event.param_len = 0;
	os_msg_post(task_id_audio_encode,&event);
}

#endif


#endif




